﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using Bamboo.Helpers;

namespace Gama.Extension
{
    public static partial class HtmlHelperExtensions
    {
        public static DropDownListBuilder<TModel, TItem> DropDownListEx<TModel, TItem>(this HtmlHelper htmlHelper, Expression<Func<TModel, object>> expression, IEnumerable<TItem> selectList)
            where TModel : class
        {
            return new DropDownListBuilder<TModel, TItem>(htmlHelper, expression).WithSelectList(selectList);
        }
    }

    public class DropDownListBuilder<TModel, TItem> : HtmlInputElementBuilder<TModel>
    {
        IEnumerable<TItem> selectList;
        Func<TItem, object> valueSelector;
        Func<TItem, object> textSelector;
        Predicate<TItem> selectedSelector;
        private string optionLabel;

        internal DropDownListBuilder(HtmlHelper htmlHelper, Expression<Func<TModel, object>> expression)
            : base(htmlHelper, expression)
        {
            // default values
            this.valueSelector = item => item.ToString();
            this.textSelector = item => item.ToString();
            this.selectedSelector = item => String.Equals(this.valueSelector(item).ToStringEx(),
                                                          this.expression.Compile()((TModel)this.htmlHelper.ViewData.Model).ToStringEx());
        }

        protected override string BuildCore()
        {
            return this.htmlHelper.DropDownList(htmlHelper.BuildBindingPath(this.expression),
                this.selectList == null ? new List<SelectListItem>()
                                        : this.selectList.Select(item => new SelectListItem { Value = this.valueSelector(item).ToStringEx(), Text = this.textSelector(item).ToStringEx(), Selected = this.selectedSelector(item) }),
                this.optionLabel, this.htmlAttributes).ToHtmlString();
        }

        internal DropDownListBuilder<TModel, TItem> WithSelectList(IEnumerable<TItem> selectList)
        {
            this.selectList = selectList;

            return this;
        }

        public DropDownListBuilder<TModel, TItem> ItemValue(Func<TItem, object> valueSelector)
        {
            this.valueSelector = valueSelector;

            return this;
        }

        public DropDownListBuilder<TModel, TItem> ItemText(Func<TItem, object> textSelector)
        {
            this.textSelector = textSelector;            

            return this;
        }

        public DropDownListBuilder<TModel, TItem> OptionLabel(string optionLabel)
        {
            this.optionLabel = optionLabel;

            return this;
        }
    }
}
